﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace YXY.Identity
{
    /// <summary>
    /// 生成表达式目录树  泛型缓存
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    public class ExpressionGenericMapper<TIn, TOut>//Mapper`2
    {
        private static Func<TIn, TOut> _FUNC = null;
        private static Func<TIn, TOut, TOut> _FUNC2 = null;
        public static TOut Trans(TIn t)
        {
            return _FUNC(t);
        }

        /// <summary>
        /// 批量实体转换
        /// </summary>
        /// <param name="list">被转换的实体List</param>
        /// <returns></returns>
        public static List<TOut> TransList(List<TIn> list)
        {
            List<TOut> outs = new List<TOut>();
            foreach (var item in list)
            {
                outs.Add(Trans(item));
            }
            return outs;
        }

        /// <summary>
        /// 把TOut 按照TIn来更新
        /// </summary>
        /// <param name="news"></param>
        /// <param name="old"></param>
        /// <returns></returns>
        public static TOut Modify(TIn news,TOut old)
        {
            return _FUNC2(news, old);
        }

        static ExpressionGenericMapper()
        {
            #region 创建构造对象的委托
            {
                ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
                List<MemberBinding> memberBindingList = new List<MemberBinding>();
                foreach (var item in typeof(TOut).GetProperties())
                {
                    var prop = typeof(TIn).GetProperty(item.Name);
                    if (prop != null)
                    {
                        MemberExpression property = Expression.Property(parameterExpression, prop);
                        MemberBinding memberBinding = Expression.Bind(item, property);
                        memberBindingList.Add(memberBinding);
                    }
                }
                foreach (var item in typeof(TOut).GetFields())
                {
                    var prop = typeof(TIn).GetField(item.Name);
                    if (prop != null)
                    {
                        MemberExpression property = Expression.Field(parameterExpression, prop);
                        MemberBinding memberBinding = Expression.Bind(item, property);
                        memberBindingList.Add(memberBinding);
                    }

                }
                MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
                Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
                {
                    parameterExpression
                });
                _FUNC = lambda.Compile();//拼装是一次性的
            }
            #endregion
            #region 修改对象的委托
            {

                


                ParameterExpression oExpression = Expression.Parameter(typeof(TOut), "o");
                ParameterExpression nExpression = Expression.Parameter(typeof(TIn), "n");
                List<MemberBinding> memberBindingList = new List<MemberBinding>();
                foreach (var item in typeof(TOut).GetProperties())
                {
                    var prop = typeof(TIn).GetProperty(item.Name);
                    if (prop != null)
                    {
                        MemberExpression property = Expression.Property(nExpression, prop);
                        MemberBinding memberBinding = Expression.Bind(item, property);
                        memberBindingList.Add(memberBinding);
                    }
                    else
                    {
                        var propOld= typeof(TOut).GetProperty(item.Name);
                        MemberExpression property = Expression.Property(oExpression, propOld);
                        MemberBinding memberBinding = Expression.Bind(item, property);
                        memberBindingList.Add(memberBinding);
                    }
                }
                foreach (var item in typeof(TOut).GetFields())
                {
                    var prop = typeof(TIn).GetField(item.Name);
                    if (prop != null)
                    {
                        MemberExpression property = Expression.Field(nExpression, prop);
                        MemberBinding memberBinding = Expression.Bind(item, property);
                        memberBindingList.Add(memberBinding);
                    }
                    else
                    {
                        var propOld = typeof(TOut).GetField(item.Name);
                        MemberExpression property = Expression.Field(oExpression, propOld);
                        MemberBinding memberBinding = Expression.Bind(item, property);
                        memberBindingList.Add(memberBinding);
                    }
                }
                MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
                Expression<Func<TIn,TOut, TOut>> lambda = Expression.Lambda<Func<TIn,TOut, TOut>>(memberInitExpression, new ParameterExpression[]
                {
                   nExpression, oExpression
                });
                _FUNC2 = lambda.Compile();//拼装是一次性的
            }
            #endregion
        }



    }
}
